#include "CpLog.h"
#include "CpSimulator.h"
#include <TFile.h>
#include "CpParticle.h"
#include <TTree.h>
#include <TLorentzVector.h>
#include "CpFunctions.h"
#include <TSystem.h>
#include <TEveManager.h>
#include <TGeoNode.h>
#include <TGeoManager.h>
#include <TEveLine.h>
#include <TEveGeoNode.h>
#include <TEveCompound.h>
#include <TStopwatch.h>

ClassImp ( CpSimulator );

//________________________________________________________________________________________________________________
CpSimulator::CpSimulator ( const char *name, const char *title ) : TNamed ( name, title ),
        fConfigFileName ( "" ),
        fGenerator ( 0 ),
        fTransporter ( 0 ) {
//
// Constructor
//

    CpDebug ( CpLog::kDebug + 5, "<-" );
    CpDebug ( CpLog::kDebug + 5, "->" );
}

//________________________________________________________________________________________________________________
CpSimulator::~CpSimulator() {
//
// Destructor.
//

    CpDebug ( CpLog::kDebug + 5, "<-" );
    delete fGenerator;
    delete fTransporter;
    CpDebug ( CpLog::kDebug + 5, "->" );

}

//________________________________________________________________________________________________________________
void CpSimulator::Run ( Long64_t nunParticles ) {
    //
    // Run simulation
    //

    TStopwatch timer;
    timer.Start();

    TString str;

    CpFunctions::Init();

    TString filename="CpSim.root";

    TGeoManager::Import("CpGeom.root");
    Double_t step = 1e-2;
    //   step=1;
    gGeoManager->SetStep(step);
    TGeoNode*nextNode;


    // Generate particles
    CpInfo ( Form ( "Generating %lld particles",nunParticles ) );
    if ( !fGenerator ) {
        CpWarning ( "No Generator available !!!" )
    }



    if ( !fTransporter ) CpError ( "No Transporter is set !!! Exiting ..." )

        TFile *f = TFile::Open(filename.Data(),"RECREATE");
    TTree *t = new TTree("cpSimTree","CpSim");
    CpParticle *part = new CpParticle() ;
    t->Branch("cpParticles",&part);

    for ( Long64_t iParticle=0; iParticle<nunParticles;iParticle++ ) {
        CpInfo ( Form ( "Processing particle %lld",iParticle ) );
        part->SetType(CpParticle::kBlood);
        part->SetID(iParticle);

        // add new track
        CpTrack *track = part->AddTrack(0);

        // generate particle
        fGenerator->Generate(track->AddPoint());
        track->GetLastPoint()->Print();
//         continue;

//         CpFunctions::kBulharConstant = 1e8;
//         if (iParticle==0) {
//           track->AddPoint(0,0,1e-3,0,0,1e-4,0);
//         }
//         if (iParticle==1) {
//           track->AddPoint(0,0,1e-3,0,0,1e-4,0);
//         }
//         if (iParticle==2) {
//           track->AddPoint(0,0,1e-3,0,0,1e-4,0);
//         }
//         if (iParticle==3) {
//           track->AddPoint(0,0,1e-3,0,0,1e-4,0);
//         }
        
//         CpFunctions::kBulharConstant = 1e7;
//         if (iParticle==0) track->AddPoint(0,0,1e-3,0,0,1e-5,0);
        
        
//         part->Print();
//         Double_t timeStep=1e0;
//         //         timeStep=50;
//         for (Double_t iTime = 0;iTime<100;iTime+=timeStep ) {
//           //           CpTrack *track = part->GetTrack(0);
//           track->GetLastPoint()->Print();
//           fTransporter->Transport ( iTime,iTime+timeStep,track);
//         }
//         t->Fill();
//         part->Clear();

        CpPoint *p = track->GetLastPoint();
        //         gGeoManager->InitTrack(p->GetX(),p->GetY(),p->GetZ(),p->GetVx(),p->GetVy(),p->GetVz());
        gGeoManager->InitTrack(p->GetX(),p->GetY(),p->GetZ(),0,0,1);
        gGeoManager->SetStep(1e-6);
        Double_t iTime = 0;
        Double_t timeMax=7.5*1e4;
        Double_t timeStep=1e0;
        Long64_t counter=0;
        Bool_t isMangetStarted=kFALSE;
        while (!gGeoManager->IsOutside() && iTime<timeMax) {
            p = track->GetLastPoint();
            gGeoManager->SetCurrentPoint(p->GetX(), p->GetY(), p->GetZ());
            nextNode = gGeoManager->Step(kFALSE);
            if (nextNode) str = nextNode->GetName();
            str = gGeoManager->GetPath();
//             const Double_t *d = gGeoManager->GetCurrentPoint();
//             if (counter++%1==0) {
//               p->Print();
//             }
//             CpInfo(Form("%s",str.Data()));
            if (str.Contains("MAGNET_1")) {
              CpFunctions::fgIsInMaget = kTRUE;
              isMangetStarted = kTRUE;
//               CpInfo("%s",str.Data());
            }
            else CpFunctions::fgIsInMaget = kFALSE;

            if (isMangetStarted && !str.Contains("VESSEL1_1")) break;
            
            CpTrack *track = part->GetTrack(0);

            fTransporter->Transport ( iTime,iTime+timeStep,track);
            iTime+=timeStep;
        }
        t->Fill();
        part->Clear();
    }

    t->Write();
    delete f;
    delete part;

    timer.Stop();
    timer.Print();


}

void CpSimulator::ShowEvent()
{
    TString fname="CpSim.root";

    TEveManager::Create();

    TGeoNode* node = gGeoManager->GetTopNode();
    TEveGeoTopNode* en = new TEveGeoTopNode(gGeoManager, node);
    //    en->SetVisLevel(100);
    en->GetNode()->GetVolume()->SetVisibility(kFALSE);

    gEve->AddGlobalElement(en);


    TEveCompound* cmp = new TEveCompound();
    cmp->SetMainColor(kGreen);
    gEve->AddElement(cmp);
    cmp->OpenCompound();


    //    Double_t initPiont[] = {0.0,0.0,0.0};
    //    Double_t initDirection[] = {0.0,0.0,1.0};
    //    gGeoManager->InitTrack(initPiont,initDirection);

    TFile *f = TFile::Open(fname.Data(), "READ");
    TTree *tree = (TTree*) f->Get("cpSimTree");
    CpParticle *part = 0;
    //   tree->Print();
    tree->SetBranchAddress("cpParticles", &part);

    CpTrack *track;
    for (Long64_t iEvent=0;iEvent<tree->GetEntries();iEvent++) {
        tree->GetEntry(iEvent);
        part->Print();
        for ( Long64_t iParticle=0; iParticle<part->GetNumberOfTracks();iParticle++ ) {
            track = (CpTrack*) part->GetTrack(iParticle);
            TEveLine *line = new TEveLine;
            line->SetMainColor(iParticle);
            for (Long64_t iPoint=0; iPoint<track->GetNumberOfPoints();iPoint++) {
                CpPoint *p = (CpPoint*) track->GetPoint(iPoint);
                line->SetNextPoint(p->GetX(),p->GetY(),p->GetZ());
            }
            cmp->AddElement(line);
        }
    }

    cmp->CloseCompound();

    gEve->Redraw3D(kTRUE);
}


